package com.cypher.encryptionanddecryption.fragment.protocol.nb25;

import android.app.DatePickerDialog;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.alibaba.fastjson.JSONObject;
import com.cypher.encryptionanddecryption.R;
import com.cypher.encryptionanddecryption.activity.BluetoothCommunicationActivity;
import com.cypher.encryptionanddecryption.bean.CommunicationBean;
import com.cypher.encryptionanddecryption.fragment.protocol.AbstractProtocolFragment;
import com.cypher.encryptionanddecryption.util.AESUtils;
import com.cypher.encryptionanddecryption.util.HexUtils;
import com.cypher.encryptionanddecryption.util.SimpleDateFormatUtils;
import com.cypher.encryptionanddecryption.util.Nb25ProtocolUtils;
import com.cypher.encryptionanddecryption.watcher.ExpandDatePickerDialog;

import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * 按条件读取界面
 * @author: 古霸天
 * @date: 2020/11/16
 */
public class TimeQuantumFragment extends AbstractProtocolFragment implements DatePickerDialog.OnDateSetListener {
    private LinearLayout parentLayout;
    private LinearLayout layout1;
    private LinearLayout layout2;
    private LinearLayout layout3;
    private EditText edit1;
    private EditText edit2;
    private EditText edit3;
    private TextView title1;
    private TextView title2;
    private TextView title3;
    private EditText result;
    private ExpandDatePickerDialog.DateViewType dateViewType = ExpandDatePickerDialog.DateViewType.DATE;
    boolean isEdit2Listener = false;
    private final String EMPTY = "";
    private BluetoothCommunicationActivity activity;
    private CommunicationBean bean;

    private Calendar calendar = Calendar.getInstance();

    public TimeQuantumFragment(BluetoothCommunicationActivity activity, CommunicationBean bean) {
        this.activity = activity;
        this.bean = bean;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_nb25_time_quantum, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        init(view);
    }

    private void init(View view) {
        edit1 = view.findViewById(R.id.time_quantum_edit1);
        edit2 = view.findViewById(R.id.time_quantum_edit2);
        edit3 = view.findViewById(R.id.time_quantum_edit3);
        edit3.setText("10");
        title1 = view.findViewById(R.id.time_quantum_title1);
        title2 = view.findViewById(R.id.time_quantum_title2);
        title3 = view.findViewById(R.id.time_quantum_title3);
        layout1 = view.findViewById(R.id.time_quantum1);
        layout2 = view.findViewById(R.id.time_quantum2);
        layout3 = view.findViewById(R.id.time_quantum3);
        parentLayout = view.findViewById(R.id.time_quantum_parent);
        result = view.findViewById(R.id.time_quantum_result);
        // 定义输入框过滤器
        InputFilter[] inputFilters = new InputFilter[1];
        // 设置输入框输入内容长度
        inputFilters[0] = new InputFilter.LengthFilter(2);
        edit3.setFilters(inputFilters);
        edit3.setInputType(InputType.TYPE_CLASS_NUMBER);

        initEditText();
        initClickHandler();
    }

    /**
     * 初始化编辑框
     */
    private void initEditText() {
        // 初始化日期时间框
        Date now = new Date();
        edit1.setText(SimpleDateFormatUtils.dateFormat.format(now));
        edit2.setText(SimpleDateFormatUtils.dateFormat.format(now));
        switch (bean.getHexCode()) {
            case "1000":
                break;
            case "1001":
                layout1.setVisibility(View.INVISIBLE);
                layout2.setVisibility(View.INVISIBLE);
                parentLayout.removeView(layout1);
                parentLayout.removeView(layout2);
                break;
            case "1006":
                dateViewType = ExpandDatePickerDialog.DateViewType.YEAR_MONTH;
                layout2.setVisibility(View.INVISIBLE);
                layout3.setVisibility(View.INVISIBLE);
                parentLayout.removeView(layout2);
                parentLayout.removeView(layout3);
                title1.setText("月份：");
                edit1.setText(SimpleDateFormatUtils.monthFormat.format(now));
                break;
            case "1106":
                dateViewType = ExpandDatePickerDialog.DateViewType.YEAR;
                layout2.setVisibility(View.INVISIBLE);
                layout3.setVisibility(View.INVISIBLE);
                parentLayout.removeView(layout2);
                parentLayout.removeView(layout3);
                edit1.setText(SimpleDateFormatUtils.yearFormat.format(now));
                title1.setText("年份：");
                break;
            default:
                layout2.setVisibility(View.INVISIBLE);
                parentLayout.removeView(layout2);
                title3.setText("天数：");
        }
    }

    /**
     * 初始化点击事件
     */
    private void initClickHandler() {

        // 日期输入框点击事件
        edit1.setOnClickListener((v) -> {

            try {
                String edit1Str = edit1.getText().toString();
                if (StringUtils.equals("1006",bean.getHexCode())) {
                    calendar.setTime(SimpleDateFormatUtils.monthFormat.parse(edit1Str));
                } else if (StringUtils.equals("1106",bean.getHexCode())) {
                    calendar.setTime(SimpleDateFormatUtils.yearFormat.parse(edit1Str));
                } else {
                    calendar.setTime(SimpleDateFormatUtils.dateFormat.parse(edit1Str));
                }

                new DatePickerDialog(activity, this
                        , calendar.get(Calendar.YEAR)
                        , calendar.get(Calendar.MONTH)
                        , calendar.get(Calendar.DAY_OF_MONTH)).show();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });

        // 时间输入框点击事件
        edit2.setOnClickListener((v) -> {
            try {
                isEdit2Listener = true;
                calendar.setTime(SimpleDateFormatUtils.dateFormat.parse(edit2.getText().toString()));
                new DatePickerDialog(activity, this
                        , calendar.get(Calendar.YEAR)
                        , calendar.get(Calendar.MONTH)
                        , calendar.get(Calendar.DAY_OF_MONTH)).show();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 日期设置成功监听
     * @param view
     * @param year
     * @param month
     * @param dayOfMonth
     */
    @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        StringBuffer dateBuf = new StringBuffer();
        dateBuf.append(year);
        switch (dateViewType) {
            case YEAR:

                break;
            case YEAR_MONTH:
                dateBuf.append("-")
                        .append(HexUtils.paddingLeft(String.valueOf(month + 1), 2));
                break;
            default:
                dateBuf.append("-")
                        .append(HexUtils.paddingLeft(String.valueOf(month + 1), 2))
                        .append("-")
                        .append(HexUtils.paddingLeft(String.valueOf(dayOfMonth), 2));
        }
        if (isEdit2Listener) {
            edit2.setText(dateBuf.toString());
            isEdit2Listener = false;
            return;
        }
        edit1.setText(dateBuf.toString());
    }

    @Override
    public void fillFragment(String data) {
        // 清空内容
        result.setText("");
        // 程序暂停0.2秒后开始渲染数据
        Runnable r = () -> {
            String formatData = Nb25ProtocolUtils.formatReceiveData(data);
            result.setText(getReader(formatData));
        };
        activity.getHandler().postDelayed(r, 200);

    }

    @Override
    public String getHexCode(String rwType) {
        return getData();
    }

    /**
     * 渲染页面
     * @param data
     */
    private String getReader(String data) {
        StringBuffer result = new StringBuffer();
        int count = 0;
        if (",1000,1001,".contains("," + bean.getHexCode() + ",")) {
            count = Integer.parseInt(data.substring(0, 2), 16);
            data = data.substring(2);
            result.append("记录条数: ").append(count).append("\n");
            Map<String, String> error = getErrorInfo();
            for (int i = 0; i < count; i++) {
                String temp = data.substring(i * 18, 18 * (i + 1));
                result.append(error.get(temp.substring(0, 4)));
                result.append(" ");
                result.append(getDateTimeFormat(temp.substring(4, 18)));
                result.append("\n");
            }
            return result.toString();
        }
        String aesKey = activity.getAesKey();
        if (StringUtils.isEmpty(aesKey)) {
            Toast.makeText(activity, "未获取到密钥", Toast.LENGTH_SHORT).show();
            return EMPTY;
        }
        count = data.length() / 32;
        StringBuffer aesBuf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            aesBuf.append(AESUtils.decrypt(aesKey, data.substring(i * 32, 32 * (i + 1))));
        }
        String aes = aesBuf.toString();
        // 切掉帧尾数据
        int len = Integer.parseInt(aes.substring(aes.length() -2), 16);
        data = aes.substring(0, aes.length() - len * 2);
        if (",1002,1004,".contains("," + bean.getHexCode() + ",")) {

            result.append("日期: ").append(aes.substring(0, 6)).append("\n");
            result.append("天数: ").append(Integer.parseInt(aes.substring(6, 8), 16)).append("\n");
            // 计算有几个小时的气量数据，去掉前面4个字节，每小时用气量4个字节
            result.append(getResult(8, 8, data));
            return result.toString();
        }
        if (StringUtils.equals("1006", bean.getHexCode())) {
            return getResult(2, 8, data);
        }
        if (",1102,1104,".contains("," + bean.getHexCode() + ",")) {

            count = (data.length() - 8) / 20;
            data = data.substring(8, count * 20 + 8);
        }
        if (StringUtils.equals("1106", bean.getHexCode())) {
            count = (data.length() - 2) / 20;
            data = data.substring(2, count * 20 + 2);
        }
        for (int i = 0; i < count; i++) {
            result.append(showDataTemp(data.substring(i * 20, 20 * (i + 1))));
        }
        return result.toString();
    }

    /**
     * 数据格式化
     * @param hex
     * @return
     */
    private String showDataTemp(String hex) {
        StringBuffer result = new StringBuffer();
        String standardCount = "0";
        String workCount = "0";
        String t = "0";
        String p = "0";

        if (!StringUtils.equals("FFFFFFFFFFFFFFFFFFFF", hex.toUpperCase())) {
            standardCount = HexUtils.getFormatDouble(
                    Integer.parseInt(hex.substring(0, 8), 16), 3);
            workCount = HexUtils.getFormatDouble(
                    Integer.parseInt(hex.substring(8, 16), 16), 3);
            t = String.valueOf(Integer.parseInt(hex.substring(16, 18), 16));
            p = String.valueOf(Integer.parseInt(hex.substring(18, 20), 16));
        }

        result.append("标况累计用: ").append(standardCount)
                .append(" 工况累计用: ").append(workCount)
                .append(" 温度: ").append(t)
                .append(" 压力: ").append(p)
                .append("\n");
        return result.toString();
    }
    /**
     * 获取结果
     * @param byteNum
     *      去掉字节数
     * @param divisor
     *      除数
     * @param data
     * @return
     */
    private String getResult(int byteNum, int divisor, String data) {
        StringBuffer result = new StringBuffer();
        int count = (data.length() - byteNum) / divisor;
        data = data.substring(byteNum, count * divisor + byteNum);
        for (int i = 0; i < count; i++) {
            String hex = data.substring(i * divisor, divisor * (i + 1));
            // 如果返回码为FFFFFFFF，说明没有数据按0处理
            if (StringUtils.equals("FFFFFFFF", hex.toUpperCase())) {
                result.append("0.000").append(" ");
                continue;
            }
            result.append(HexUtils.getFormatDouble(
                    Integer.parseInt(hex, 16), 3));
            result.append(" ");
        }
        return result.toString();
    }

    /**
     * 获取写入数据
     * @return
     */
    private String getData(){
        // 组包
        try {
            String edit1Str = edit1.getText().toString();
            Date edit1Data = null;
            String edit3Data = edit3.getText().toString();

            SimpleDateFormat format = null;
            StringBuffer data = new StringBuffer();
            if (",1000,1001,".contains("," + bean.getHexCode() + ",")) {
                if (!isNotEmpty(edit3Data, "记录条数")) return EMPTY;

                edit1Data = SimpleDateFormatUtils.dateFormat.parse(edit1Str);

                data.append("FFFF");

                if (StringUtils.equals("1000", bean.getHexCode())) {

                    format = new SimpleDateFormat("yyMMdd");

                    Date edit2Data = SimpleDateFormatUtils.dateFormat.parse(edit2.getText().toString());

                    data.append(format.format(edit1Data)).append("000000")
                            .append(format.format(edit2Data)).append("235959");

                }
                data.append(getDays(Integer.parseInt(edit3Data)));

                return getData(data.toString());
            }
            if (",1002,1004,1102,1104,".contains("," + bean.getHexCode() + ",")) {
                if (!isNotEmpty(edit3Data, "天数")) return EMPTY;

                edit1Data = SimpleDateFormatUtils.dateFormat.parse(edit1Str);

                format = new SimpleDateFormat("yyMMdd");

                data.append(format.format(edit1Data));
                data.append(getDays(Integer.parseInt(edit3Data)));

                return getData(data.toString());
            }
            if (",1006,1106,".contains("," + bean.getHexCode() + ",")) {
                if (StringUtils.equals("1006", bean.getHexCode())) {

                    format = new SimpleDateFormat("yyMM");
                    edit1Data = SimpleDateFormatUtils.monthFormat.parse(edit1Str);

                } else if (StringUtils.equals("1106", bean.getHexCode())) {

                    format = new SimpleDateFormat("yy");
                    edit1Data = SimpleDateFormatUtils.yearFormat.parse(edit1Str);
                }
                data.append(format.format(edit1Data));

                return getData(data.toString());
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return EMPTY;
    }

    private String getData(String data) {
        return Nb25ProtocolUtils.getCommand(bean.getHexCode(), data, "87", PROTOCOL_VERSION, 1);
    }
    private boolean isNotEmpty(String edit3, String content) {
        if (StringUtils.isEmpty(edit3)) {
            Toast.makeText(activity, content, Toast.LENGTH_SHORT).show();
            return false;
        }
        return true;
    }
    private String getDays(Integer days) {
        return HexUtils.paddingLeft(Integer.toHexString(days), 2).toUpperCase();
    }

    private Map<String, String> getErrorInfo() {
        String errorInfo = "{\"0001\": \"开阀\", \"0002\": \"关阀\"," +
                "\"0003\": \"重新启动\", \"0004\": \"电量低\"," +
                "\"0005\": \"电量不足\", \"0006\": \"磁干扰\"," +
                "\"0007\": \"电源断电\", \"0008\": \"异常大流量\"," +
                "\"0009\": \"计量处理单元异常\", \"000A\": \"外壳拆卸\"," +
                "\"000B\": \"异常小流量\", \"000C\": \"温度传感器异常\"," +
                "\"000D\": \"压力传感器异常\", \"000E\": \"阀门直通报警\", \"000F\": \"外部报警器报警\"}";
        return JSONObject.parseObject(errorInfo, Map.class);
    }
    private String getDateTimeFormat(String data) {
        StringBuffer buf = new StringBuffer("20");
        buf.append(data.substring(0, 2));
        buf.append("-");
        buf.append(data.substring(2, 4));
        buf.append("-");
        buf.append(data.substring(4, 6));
        buf.append(" ");
        buf.append(data.substring(8, 10));
        buf.append(":");
        buf.append(data.substring(10, 12));
        buf.append(":");
        buf.append(data.substring(12, 14));
        return buf.toString();
    }
}
